# cli_client.py
import socket
import threading
import json
import time
import os
import hashlib
import sys

class CLIChatClient:
    def __init__(self, nickname, server_ip, server_port):
        self.nickname = nickname
        self.server_ip = server_ip
        self.server_port = server_port
        self.client_socket = None
        self.running = False
        
    def connect(self):
        """连接到服务器"""
        try:
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.connect((self.server_ip, self.server_port))
            # 发送昵称
            self.client_socket.send(self.nickname.encode("utf-8"))
            self.running = True
            print(f"已连接到服务器 {self.server_ip}:{self.server_port}")
            print("输入消息并按回车发送，输入 'quit' 或 'exit' 退出")
            return True
        except Exception as e:
            print(f"连接失败: {e}")
            return False
            
    def send_message(self, content):
        """发送文本消息"""
        try:
            msg_data = json.dumps({
                "type": "message",
                "sender": self.nickname,
                "content": content,
                "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
            })
            self.client_socket.send(msg_data.encode("utf-8"))
            return True
        except Exception as e:
            print(f"发送消息失败: {e}")
            return False
            
    def receive_messages(self):
        """接收消息线程"""
        while self.running:
            try:
                data = self.client_socket.recv(4096)
                if not data:
                    break
                    
                # 处理心跳响应
                if data == b"HEARTBEAT_RESPONSE":
                    continue
                    
                # 处理普通消息
                try:
                    message = json.loads(data.decode('utf-8'))
                    if message["type"] == "message":
                        sender = message["sender"]
                        content = message["content"]
                        timestamp = message.get("timestamp", time.strftime("%Y-%m-%d %H:%M:%S"))
                        
                        # 显示消息
                        if sender == self.nickname:
                            print(f"[{timestamp}] {sender} (你): {content}")
                        else:
                            print(f"[{timestamp}] {sender}: {content}")
                            
                except json.JSONDecodeError:
                    print("收到无效消息格式")
                except Exception as e:
                    print(f"消息处理错误: {e}")
                    
            except Exception as e:
                if self.running:
                    print(f"连接异常: {e}")
                break
                
        # 连接断开
        if self.running:
            print("与服务器的连接已断开")
            self.running = False
            
    def run(self):
        """运行客户端"""
        if not self.connect():
            return
            
        # 启动接收消息线程
        receive_thread = threading.Thread(target=self.receive_messages, daemon=True)
        receive_thread.start()
        
        try:
            # 主循环处理用户输入
            while self.running:
                try:
                    # 非阻塞读取用户输入
                    message = input()
                    
                    if message.lower() in ['quit', 'exit']:
                        print("正在退出...")
                        break
                        
                    if message.strip():
                        self.send_message(message)
                        
                except KeyboardInterrupt:
                    print("\n正在退出...")
                    break
                except EOFError:
                    break
                    
        finally:
            self.running = False
            if self.client_socket:
                self.client_socket.close()
            print("客户端已退出")

def load_settings():
    """加载配置"""
    try:
        with open(os.path.join("config", "client_settings.json"), "r", encoding="utf-8") as f:
            settings = json.load(f)
            settings.setdefault("server_ip", "127.0.0.1")
            settings.setdefault("server_port", 12345)
            return settings
    except (FileNotFoundError, json.JSONDecodeError):
        return {"server_ip": "127.0.0.1", "server_port": 12345}

def main():
    """主函数"""
    # 创建必要目录
    for d in [os.path.join("config"), os.path.join("config", "chat_logs")]:
        if not os.path.exists(d):
            os.makedirs(d)
            
    # 加载设置
    settings = load_settings()
    
    # 获取昵称
    if len(sys.argv) > 1:
        nickname = sys.argv[1]
    else:
        nickname = input("请输入用户名: ").strip()
        
    if not nickname:
        print("用户名不能为空")
        return
        
    # 保存昵称到配置
    settings["nickname"] = nickname
    try:
        with open(os.path.join("config", "client_settings.json"), "w", encoding="utf-8") as f:
            json.dump(settings, f, indent=2)
    except Exception as e:
        print(f"保存配置失败: {e}")
    
    # 创建并运行客户端
    client = CLIChatClient(
        nickname=nickname,
        server_ip=settings["server_ip"],
        server_port=int(settings["server_port"])
    )
    client.run()

if __name__ == "__main__":
    main()
